package br.usp.pcs.poli.lti.iToo;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseWheelListener;
import java.awt.geom.Point2D;
import java.beans.BeanInfo;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;

import br.usp.pcs.poli.lti.iToo.tutor.model.AddClassDomainAction;
import br.usp.pcs.poli.lti.iToo.tutor.model.ITooDomainModel;

import com.horstmann.violet.framework.dialog.DialogFactory;
import com.horstmann.violet.framework.file.GraphFile;
import com.horstmann.violet.framework.file.IFile;
import com.horstmann.violet.framework.file.IGraphFile;
import com.horstmann.violet.framework.injection.bean.ManiocFramework.BeanInjector;
import com.horstmann.violet.framework.injection.bean.ManiocFramework.InjectedBean;
import com.horstmann.violet.framework.injection.resources.ResourceBundleInjector;
import com.horstmann.violet.framework.injection.resources.annotation.ResourceBundleBean;
import com.horstmann.violet.framework.theme.ITheme;
import com.horstmann.violet.framework.theme.ThemeManager;
import com.horstmann.violet.product.diagram.abstracts.IGraph;
import com.horstmann.violet.product.diagram.abstracts.node.AbstractNode;
import com.horstmann.violet.product.diagram.abstracts.property.ArrowHead;
import com.horstmann.violet.product.diagram.abstracts.property.BentStyle;
import com.horstmann.violet.product.diagram.abstracts.property.LineStyle;
import com.horstmann.violet.workspace.IWorkspace;
import com.horstmann.violet.workspace.IWorkspaceListener;
import com.horstmann.violet.workspace.Workspace;



public class MainFrame extends JFrame {
	/**
	 * 
	 */
	private static final long serialVersionUID = -701544365156780611L;

	public MainFrame()
    {
		BeanInjector.getInjector().inject(this);
        //ResourceBundleInjector.getInjector().inject(this);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.dialogFactory.setDialogOwner(this);
        decorateFrame();
        setInitialSize();
        createMenuBar();
        getContentPane().add(this.getMainPanel());
        
    }
	
	private void createMenuBar() {
		JMenuBar menuBar = new JMenuBar();
        JMenu menu = new JMenu("teste");
        JMenuItem menuItem = new JMenuItem("Teste");
        menuItem.addActionListener(new ActionListener() {
        	public void actionPerformed(ActionEvent event)
            {
        		ITooDomainModel model = new ITooDomainModel();
                AddClassDomainAction action = new AddClassDomainAction("AddClass", "AddClass");
                action.setDomainModel(model);
                action.execute();
            }
        });
        menu.add(menuItem);
        getContentPane().add(menu);
        menuBar.add(menu);
        setJMenuBar(menuBar);
	}

	private void decorateFrame()
    {
        setTitle("Teste");
    }
	
    /**
     * Sets initial size on startup
     */
    private void setInitialSize()
    {
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        int screenWidth = (int) screenSize.getWidth();
        int screenHeight = (int) screenSize.getHeight();
        setBounds(screenWidth / 16, screenHeight / 16, screenWidth * 7 / 8, screenHeight * 7 / 8);
        // For screenshots only -> setBounds(50, 50, 850, 650);
    }
    
    private JPanel getMainPanel() {
        if (this.mainPanel == null) {
            this.mainPanel = new JPanel(new BorderLayout());
            this.mainPanel.setBorder(new EmptyBorder(0, 0, 0, 0));
            JPanel bottomBorderPanel = new JPanel();
            ITheme cLAF = this.themeManager.getTheme();
            bottomBorderPanel.setBackground(cLAF.getMenubarBackgroundColor().darker());
            bottomBorderPanel.setBorder(new EmptyBorder(0, 0, 0, 0));
            bottomBorderPanel.setSize(getContentPane().getWidth(), 8);
            this.mainPanel.add(bottomBorderPanel, BorderLayout.SOUTH);
        }
        return this.mainPanel;
    }
    

    /**
     * @return the tabbed pane that contains diagram panels
     */
    public JTabbedPane getTabbedPane()
    {
        if (this.tabbedPane == null)
        {
            this.tabbedPane = new JTabbedPane()
            {
                public void paint(Graphics g)
                {
                    Graphics2D g2 = (Graphics2D) g;
                    Paint currentPaint = g2.getPaint();
                    ITheme LAF = themeManager.getTheme();
                    GradientPaint paint = new GradientPaint(getWidth() / 2, -getHeight() / 4, LAF.getWelcomeBackgroundStartColor(),
                            getWidth() / 2, getHeight() + getHeight() / 4, LAF.getWelcomeBackgroundEndColor());
                    g2.setPaint(paint);
                    g2.fillRect(0, 0, getWidth(), getHeight());
                    g2.setPaint(currentPaint);
                    super.paint(g);
                }
            };
            this.tabbedPane.setOpaque(false);
            MouseWheelListener[] mouseWheelListeners = this.tabbedPane.getMouseWheelListeners();
            for (int i = 0; i < mouseWheelListeners.length; i++)
            {
                this.tabbedPane.removeMouseWheelListener(mouseWheelListeners[i]);
            }
        }
        return this.tabbedPane;
    }
    
    /**
     * Adds a tabbed pane (only if not already added)
     * 
     * @param c the component to display in the internal frame
     */
    public void addTabbedPane(final IWorkspace workspace)
    {
        JTabbedPane tabbedPane = getTabbedPane();
        getMainPanel().add(tabbedPane, BorderLayout.CENTER);
        repaint();
        if (this.workspaceList.contains(workspace))
        {
            return;
        }
        this.workspaceList.add(workspace);
        this.getTabbedPane().add(workspace.getTitle(), workspace.getAWTComponent());
        listenToDiagramPanelEvents(workspace);
        getTabbedPane().setSelectedIndex(workspaceList.size() - 1);
        workspace.getEditorPart().getSwingComponent().requestFocus();
    }
    
    public List<IWorkspace> getWorkspaceList()
    {
        return workspaceList;
    }
    
    /**
     * @return selected diagram file path (or null if not one is selected; that should never happen)
     */
    public IWorkspace getActiveWorkspace()
    {
        JTabbedPane tp = getTabbedPane();
        int pos = tp.getSelectedIndex();
        if (pos >= 0)
        {
            return this.workspaceList.get(pos);
        }
        throw new RuntimeException("Error while retreiving current active diagram panel");
    }
    
    /**
     * Add a listener to perform action when something happens on this diagram
     * 
     * @param diagramPanel
     */
    private void listenToDiagramPanelEvents(final IWorkspace diagramPanel)
    {
        diagramPanel.addListener(new IWorkspaceListener()
        {
            public void titleChanged(String newTitle)
            {
                int pos = workspaceList.indexOf(diagramPanel);
                getTabbedPane().setTitleAt(pos, newTitle);
            }

            public void graphCouldBeSaved()
            {
                // nothing to do here
            }

            public void mustOpenfile(IFile file)
            {
                try
                {
                    IGraphFile graphFile = new GraphFile(file);
                    IWorkspace newWorkspace = new Workspace(graphFile);
                    addTabbedPane(newWorkspace);
                }
                catch (IOException e)
                {
                    DialogFactory.getInstance().showErrorDialog(e.getMessage());
                }
            }
        });
    }
    
    /**
     * All disgram workspaces
     */
    private List<IWorkspace> workspaceList = new ArrayList<IWorkspace>();
    
    /**
     * Tabbed pane instance
     */
    private JTabbedPane tabbedPane;
    
    /**
     * Main panel
     */
    private JPanel mainPanel;
    
    @InjectedBean
    private ThemeManager themeManager;
    
    /**
     * Needed to display dialog boxes
     */
    @InjectedBean
    private DialogFactory dialogFactory;
    
 // workaround for bug #4646747 in J2SE SDK 1.4.0
    private static java.util.HashMap<Class<?>, BeanInfo> beanInfos;
    static
    {
        beanInfos = new java.util.HashMap<Class<?>, BeanInfo>();
        Class<?>[] cls = new Class<?>[]
        {
                Point2D.Double.class,
                BentStyle.class,
                ArrowHead.class,
                LineStyle.class,
                IGraph.class,
                AbstractNode.class,
        };
        for (int i = 0; i < cls.length; i++)
        {
            try
            {
                beanInfos.put(cls[i], java.beans.Introspector.getBeanInfo(cls[i]));
            }
            catch (java.beans.IntrospectionException ex)
            {
            }
        }
    }
}
